PreprocMRI.m 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642
  1. function varargout = PreprocMRI(varargin)
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. % Reads MRI data into Fieldtrip and runs preprocessing. %
  4. % See: "help ft_read_mri" for supported filetypes. %
  5. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  6. % Copyright (C) 2013-2014, Michael J. Cheung
  7. %
  8. % This file is a part of the MEG & PLS Pipeline (MEGPLS). For more
  9. % details, see the documentation included with the software package.
  10. %
  11. % MEGPLS is free software: you can redistribute it and/or modify it under
  12. % the terms of the GNU General Public License version 2 as published by
  13. % the Free Software Foundation. This program is distributed in the hope
  14. % that it will be useful, but WITHOUT ANY WARRANTY; without even the
  15. % implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16. % See the GNU General Public License for more details.
  17. %
  18. % You should have received a copy of the GNU General Public License along
  19. % with this program. If not, you can download the license here:
  20. % <http://www.gnu.org/licenses/old-licenses/gpl-2.0>.
  21. % Last Modified by GUIDE v2.5 21-Aug-2014 12:07:40
  22. % Begin initialization code - DO NOT EDIT
  23. gui_Singleton = 1;
  24. gui_State = struct('gui_Name', mfilename, ...
  25. 'gui_Singleton', gui_Singleton, ...
  26. 'gui_OpeningFcn', @PreprocMRI_OpeningFcn, ...
  27. 'gui_OutputFcn', @PreprocMRI_OutputFcn, ...
  28. 'gui_LayoutFcn', [] , ...
  29. 'gui_Callback', []);
  30. if nargin && ischar(varargin{1})
  31. gui_State.gui_Callback = str2func(varargin{1});
  32. end
  33. if nargout
  34. [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
  35. else
  36. gui_mainfcn(gui_State, varargin{:});
  37. end
  38. % End initialization code - DO NOT EDIT
  39. %--- Executes just before PreprocMRI is made visible. ---%
  40. %--------------------------------------------------------%
  41. function PreprocMRI_OpeningFcn(hObject, eventdata, handles, varargin)
  42. % This function has no output args, see OutputFcn.
  43. % hObject handle to figure
  44. % eventdata reserved - to be defined in a future version of MATLAB
  45. % handles structure with handles and user data (see GUIDATA)
  46. % varargin command line arguments to PreprocMRI (see VARARGIN)
  47. % Choose default command line output for PreprocMRI
  48. handles.output = hObject;
  49. % Update handles structure
  50. guidata(hObject, handles);
  51. % Make sure toolbox paths are added:
  52. [PipelineDir, ~, ~] = fileparts(which('PreprocMRI.m'));
  53. addpath(genpath(PipelineDir));
  54. rmpath([PipelineDir,'/DEFAULT_SETTINGS']); % Make sure its calling from AnalysisID
  55. rmpath([PipelineDir,'/TEMPORARY_FIXES']); % Make sure its calling from FT toolbox
  56. CheckToolboxPaths(PipelineDir);
  57. if exist('ErrorLog_PreprocMRI.txt', 'file')
  58. delete('ErrorLog_PreprocMRI.txt');
  59. end
  60. % Initialize variables:
  61. handles.paths.Rootpath = [];
  62. handles.paths.AnatID = [];
  63. handles.name.AnatID = [];
  64. handles.paths.CurrentGroupID = [];
  65. handles.name.CurrentGroupID = [];
  66. handles.name.SubjID = [];
  67. handles.gui.Status = [];
  68. handles.paths.AnatFolder = [];
  69. handles.paths.AnatFile = [];
  70. handles.paths.AnatFullpath = [];
  71. handles.paths.PreprocMRI = [];
  72. handles.FTcfg = [];
  73. handles.gui.ShowInstruct = 1;
  74. % Save handles:
  75. guidata(hObject, handles);
  76. % UIWAIT makes PreprocMRI wait for user response (see UIRESUME)
  77. % uiwait(handles.figure1);
  78. %--- Outputs from this function are returned to the command line. ---%
  79. %--------------------------------------------------------------------%
  80. function varargout = PreprocMRI_OutputFcn(hObject, eventdata, handles)
  81. % varargout cell array for returning output args (see VARARGOUT);
  82. % hObject handle to figure
  83. % eventdata reserved - to be defined in a future version of MATLAB
  84. % handles structure with handles and user data (see GUIDATA)
  85. % Get default command line output from handles structure
  86. varargout{1} = handles.output;
  87. %===================================%
  88. % FUNCTIONS FOR SELECTING ROOTPATH: %
  89. %===================================%
  90. %--- Executes on button press in ButtonSetRootpath. ---%
  91. %------------------------------------------------------%
  92. function ButtonSetRootpath_Callback(hObject, eventdata, handles)
  93. if ~isempty(handles.name.AnatID)
  94. prompt = {'WARNING:';
  95. 'Changing root directory will clear all current settings.'; '';
  96. 'Do you wish to continue?'};
  97. ChangeDir = questdlg(prompt, 'WARNING:', 'YES', 'NO', 'NO');
  98. if strcmp(ChangeDir, 'NO')
  99. return;
  100. end
  101. end
  102. % Select and set rootpath:
  103. SelectedPath = uigetdir;
  104. if SelectedPath == 0
  105. return; % If user cancels
  106. end
  107. % Check if selected path has spaces (AFNI functions cannot read spaces):
  108. CheckSpaces = strfind(SelectedPath, ' ');
  109. if ~isempty(CheckSpaces)
  110. message = {'Error: Target directory selected contains spaces.';
  111. 'AFNI functions cannot read folder & file paths with spaces.';
  112. 'AFNI functions are required for file conversions later on.'};
  113. msgbox(message, 'Error:')
  114. return;
  115. end
  116. handles.paths.Rootpath = SelectedPath;
  117. set(handles.TextboxRootpath, 'String', handles.paths.Rootpath);
  118. % Start Waitbox:
  119. WaitBox = StartWaitBox('SETTING TARGET DIRECTORY:');
  120. % Reset AnatID:
  121. handles.name.AnatID = [];
  122. handles.paths.AnatID = [];
  123. set(handles.TextboxAnatID, 'String', 'None Selected');
  124. % Reset GroupID:
  125. handles.name.CurrentGroupID = [];
  126. handles.paths.CurrentGroupID = [];
  127. set(handles.TextboxGroupID, 'String', 'None Selected');
  128. % Reset settings & GUI panels:
  129. handles = ResetSubjIDSettings (handles);
  130. handles = ResetInputAnatSettings (handles);
  131. handles = ResetStatusSettings (handles);
  132. handles = ResetPreprocSettings (handles);
  133. % Update settings & GUI panels (to enable/disable):
  134. handles = UpdateSubjIDSettings (handles);
  135. handles = UpdateInputAnatSettings (handles);
  136. handles = UpdateStatusSettings (handles);
  137. handles = UpdatePreprocSettings (handles);
  138. % Save handles:
  139. guidata(hObject, handles);
  140. close(WaitBox);
  141. %--- Textbox to display selected Rootpath: ---%
  142. %---------------------------------------------%
  143. function TextboxRootpath_Callback(hObject, eventdata, handles)
  144. EnteredText = get(handles.TextboxRootpath, 'String');
  145. if ~isequal(EnteredText, handles.paths.Rootpath)
  146. set(handles.TextboxRootpath, 'String', handles.paths.Rootpath);
  147. msgbox('Note: Use button to change Rootpath.')
  148. end
  149. %===========================================%
  150. % FUNCTIONS FOR CREATING OR LOADING ANATID: %
  151. %===========================================%
  152. %--- Executes on button press in ButtonCreateAnatID. ---%
  153. %-------------------------------------------------------%
  154. function ButtonCreateAnatID_Callback(hObject, eventdata, handles)
  155. if isempty(handles.paths.Rootpath)
  156. msgbox('Warning: Select root directory first.', 'Warning:');
  157. return;
  158. end
  159. % Enter name of AnatID:
  160. UserInput = inputdlg('Enter AnatID name:', 'Create new AnatID:');
  161. UserInput = deblank(UserInput);
  162. UserInput = regexprep(UserInput, '\s+', '_');
  163. if isempty(char(UserInput))
  164. return; % If user cancels
  165. end
  166. PathInputID = [handles.paths.Rootpath,'/AnatID_',UserInput{1}];
  167. if exist(PathInputID, 'dir')
  168. msgbox('Error: Specified AnatID already exists!', 'Error:')
  169. return;
  170. end
  171. % Set AnatID & create folder:
  172. status = mkdir(PathInputID);
  173. if status == 1 % If mkdir successful
  174. handles.name.AnatID = UserInput{1};
  175. handles.paths.AnatID = PathInputID;
  176. set(handles.TextboxAnatID, 'String', handles.name.AnatID);
  177. else
  178. msgbox('Error: Failed to create AnatID folder.', 'Error:')
  179. return;
  180. end
  181. % Start Waitbox:
  182. WaitBox = StartWaitBox('CREATING ANAT ID:');
  183. % Reset GroupID:
  184. handles.name.CurrentGroupID = [];
  185. handles.paths.CurrentGroupID = [];
  186. set(handles.TextboxGroupID, 'String', []);
  187. % Reset settings & GUI panels:
  188. handles = ResetSubjIDSettings (handles);
  189. handles = ResetInputAnatSettings (handles);
  190. handles = ResetStatusSettings (handles);
  191. handles = ResetPreprocSettings (handles);
  192. % Update settings & GUI panels (to enable/disable):
  193. handles = UpdateSubjIDSettings (handles);
  194. handles = UpdateInputAnatSettings (handles);
  195. handles = UpdateStatusSettings (handles);
  196. handles = UpdatePreprocSettings (handles);
  197. % Save handles:
  198. guidata(hObject, handles);
  199. close(WaitBox);
  200. %--- Executes on button press in ButtonLoadAnatID. ---%
  201. %-----------------------------------------------------%
  202. function ButtonLoadAnatID_Callback(hObject, eventdata, handles)
  203. if isempty(handles.paths.Rootpath)
  204. msgbox('Warning: Select root directory first.', 'Warning:');
  205. return;
  206. end
  207. % Get AnatID folders in current rootpath:
  208. DetectedFolders = dir([handles.paths.Rootpath,'/AnatID_*']);
  209. RemoveIndex = [];
  210. for d = 1:length(DetectedFolders)
  211. if DetectedFolders(d).isdir ~= 1
  212. RemoveIndex = [RemoveIndex, d]; % Get unwanted indices
  213. end
  214. end
  215. DetectedFolders(RemoveIndex) = [];
  216. if isempty(DetectedFolders)
  217. msgbox('Error: No AnatID folders detected inside root dir.', 'Error:');
  218. return;
  219. end
  220. % List AnatID folders for selection:
  221. DetectedFolders = {DetectedFolders.name};
  222. SelectedIndex = listdlg('PromptString', 'Select AnatID to load:',...
  223. 'ListSize', [300, 300], 'SelectionMode', 'single', 'ListString', DetectedFolders);
  224. if isempty(SelectedIndex)
  225. return; % If user cancels.
  226. end
  227. SelectedAnatID = DetectedFolders{SelectedIndex};
  228. SelectedAnatID(1:7) = []; % Remove "AnatID_" prefix to get AnatID suffix.
  229. FullpathAnatID = [handles.paths.Rootpath,'/AnatID_',SelectedAnatID];
  230. % Set as current AnatID:
  231. handles.name.AnatID = SelectedAnatID;
  232. handles.paths.AnatID = FullpathAnatID;
  233. set(handles.TextboxAnatID, 'String', handles.name.AnatID);
  234. % Start Waitbox:
  235. WaitBox = StartWaitBox('LOADING ANAT ID:');
  236. % Reset GroupID:
  237. handles.name.CurrentGroupID = [];
  238. handles.paths.CurrentGroupID = [];
  239. set(handles.TextboxGroupID, 'String', []);
  240. % Reset settings & GUI panels:
  241. handles = ResetSubjIDSettings (handles);
  242. handles = ResetInputAnatSettings (handles);
  243. handles = ResetStatusSettings (handles);
  244. handles = ResetPreprocSettings (handles);
  245. % Update settings & GUI panels (to enable/disable):
  246. handles = UpdateSubjIDSettings (handles);
  247. handles = UpdateInputAnatSettings (handles);
  248. handles = UpdateStatusSettings (handles);
  249. handles = UpdatePreprocSettings (handles);
  250. % Save handles:
  251. guidata(hObject, handles);
  252. close(WaitBox);
  253. %--- Textbox to display current AnatID: ---%
  254. %------------------------------------------%
  255. function TextboxAnatID_Callback(hObject, eventdata, handles)
  256. EnteredText = get(handles.TextboxAnatID, 'String');
  257. if ~isequal(EnteredText, handles.name.AnatID)
  258. set(handles.TextboxAnatID, 'String', handles.name.AnatID);
  259. msgbox('Note: Use button to change AnatID.')
  260. end
  261. %===========================================%
  262. % FNCTIONS FOR CREATING OR LOADING GROUPID: %
  263. %===========================================%
  264. %--- Executes on button press in ButtonCreateGroupID. ---%
  265. %--------------------------------------------------------%
  266. function ButtonCreateGroupID_Callback(hObject, eventdata, handles)
  267. if isempty(handles.paths.Rootpath)
  268. msgbox('Warning: Select root directory first.', 'Warning:');
  269. return;
  270. end
  271. if isempty(handles.name.AnatID) || isempty(handles.paths.AnatID)
  272. msgbox('Warning: Create or load AnatID first.', 'Warning:');
  273. return;
  274. end
  275. % Enter name of GroupID:
  276. UserInput = inputdlg('Enter GroupID name:', 'Create new GroupID:');
  277. UserInput = deblank(UserInput);
  278. UserInput = regexprep(UserInput, '\s+', '_');
  279. if isempty(char(UserInput))
  280. return; % If user cancels
  281. end
  282. PathInputID = [handles.paths.AnatID,'/GroupID_',UserInput{1}];
  283. if exist(PathInputID, 'dir')
  284. msgbox('Error: Specified GroupID already exists for this AnatID.', 'Error:')
  285. return;
  286. end
  287. % Set GroupID and create folder:
  288. status = mkdir(PathInputID);
  289. if status == 1 % If mkdir successful
  290. handles.name.CurrentGroupID = UserInput{1};
  291. handles.paths.CurrentGroupID = PathInputID;
  292. set(handles.TextboxGroupID, 'String', handles.name.CurrentGroupID);
  293. else
  294. msgbox('Error: Failed to create GroupID folder.', 'Error:')
  295. return;
  296. end
  297. % Start Waitbox:
  298. WaitBox = StartWaitBox('CREATING GROUP ID:');
  299. % Reset settings & GUI panels:
  300. handles = ResetSubjIDSettings (handles);
  301. handles = ResetInputAnatSettings (handles);
  302. handles = ResetStatusSettings (handles);
  303. handles = ResetPreprocSettings (handles);
  304. % Update settings & GUI panels (to enable/disable):
  305. handles = UpdateSubjIDSettings (handles);
  306. handles = UpdateInputAnatSettings (handles);
  307. handles = UpdateStatusSettings (handles);
  308. handles = UpdatePreprocSettings (handles);
  309. % Save handles:
  310. guidata(hObject, handles);
  311. close(WaitBox);
  312. %--- Executes on button press in ButtonLoadGroupID. ---%
  313. %------------------------------------------------------%
  314. function ButtonLoadGroupID_Callback(hObject, eventdata, handles)
  315. if isempty(handles.paths.Rootpath)
  316. msgbox('Warning: Select root directory first.', 'Warning:');
  317. return;
  318. end
  319. if isempty(handles.name.AnatID) || isempty(handles.paths.AnatID)
  320. msgbox('Warning: Create or load AnatID first.', 'Warning:');
  321. return;
  322. end
  323. % Acquire GroupID folders for current AnatID:
  324. DetectedFolders = dir([handles.paths.AnatID,'/GroupID_*']);
  325. RemoveIndex = [];
  326. for g = 1:length(DetectedFolders)
  327. if DetectedFolders(g).isdir ~= 1
  328. RemoveIndex = [RemoveIndex, g]; % Get unwanted indices
  329. end
  330. end
  331. DetectedFolders(RemoveIndex) = [];
  332. if isempty(DetectedFolders)
  333. msgbox('Error: No GroupID folders were detected for current AnatID.', 'Error:');
  334. return;
  335. end
  336. % List detected GroupID folders for selection:
  337. DetectedFolders = {DetectedFolders.name};
  338. SelectedIndex = listdlg('PromptString', 'Select GroupID to load:',...
  339. 'ListSize', [300, 300], 'SelectionMode', 'single', 'ListString', DetectedFolders);
  340. if isempty(SelectedIndex)
  341. return; % If user cancels
  342. end
  343. SelectedGroupID = DetectedFolders{SelectedIndex};
  344. SelectedGroupID(1:8) = []; % Remove "GroupID_" prefix to get GroupID.
  345. % Set as current GroupID:
  346. handles.name.CurrentGroupID = SelectedGroupID;
  347. handles.paths.CurrentGroupID = [handles.paths.AnatID,'/GroupID_',SelectedGroupID];
  348. set(handles.TextboxGroupID, 'String', handles.name.CurrentGroupID);
  349. % Start Waitbox:
  350. WaitBox = StartWaitBox('LOADING GROUP ID:');
  351. % Reset settings & GUI panels:
  352. handles = ResetSubjIDSettings (handles);
  353. handles = ResetInputAnatSettings (handles);
  354. handles = ResetStatusSettings (handles);
  355. handles = ResetPreprocSettings (handles);
  356. % Load PreprocInputMRI .mat for GroupID if available:
  357. PreprocInputMat = [handles.paths.CurrentGroupID,...
  358. '/PreprocInputMRI_',handles.name.CurrentGroupID,'.mat'];
  359. if exist(PreprocInputMat, 'file')
  360. LoadedMat = load(PreprocInputMat);
  361. handles = LoadSubjIDSettings (handles, LoadedMat);
  362. handles = LoadInputAnatSettings (handles, LoadedMat);
  363. else
  364. message = {'WARNING:';
  365. 'PreprocInputMRI .mat file not found for GroupID.';
  366. 'SubjIDs and input MRI files will need to be selected again.'};
  367. msgbox(message, 'Warning:');
  368. end
  369. % Update settings & GUI panels (to enable/disable):
  370. handles = UpdateSubjIDSettings (handles);
  371. handles = UpdateInputAnatSettings (handles);
  372. handles = UpdatePreprocSettings (handles);
  373. % Update status for all loaded subjects:
  374. StatusWaitbar = waitbar(0, ...
  375. 'Please wait. Loading files from session.', 'Windowstyle', 'modal');
  376. for s = 1:length(handles.name.SubjID)
  377. waitbar(s/length(handles.name.SubjID), StatusWaitbar);
  378. handles = DetectStatus(handles, s);
  379. end
  380. delete(StatusWaitbar)
  381. handles = UpdateStatusSettings(handles);
  382. % Save handles:
  383. guidata(hObject, handles);
  384. close(WaitBox);
  385. %--- Textbox to display current GroupID: ---%
  386. %-------------------------------------------%
  387. function TextboxGroupID_Callback(hObject, eventdata, handles)
  388. EnteredText = get(handles.TextboxGroupID, 'String');
  389. if ~isequal(EnteredText, handles.name.CurrentGroupID)
  390. set(handles.TextboxGroupID, 'String', handles.name.CurrentGroupID);
  391. msgbox('Note: Use button to change GroupID.')
  392. end
  393. %============================================%
  394. % FUNCTIONS FOR ADDING OR REMOVING SUBJECTS: %
  395. %============================================%
  396. %--- Executes on selection change in ListboxSubjID. ---%
  397. %------------------------------------------------------%
  398. function ListboxSubjID_Callback(hObject, eventdata, handles)
  399. SelectedIndex = get(handles.ListboxSubjID, 'Value');
  400. set(handles.ListboxInputAnat, 'Value', SelectedIndex);
  401. set(handles.ListboxStatus, 'Value', SelectedIndex);
  402. handles = UpdatePreprocSettings(handles); % For enable/disable
  403. guidata(hObject, handles);
  404. %--- User enters SubjID into textbox. ---%
  405. %----------------------------------------%
  406. function TextboxSubjID_Callback(hObject, eventdata, handles)
  407. keypress = get(gcf, 'CurrentCharacter');
  408. if isequal(keypress, char(13))
  409. ButtonAddSubjID_Callback(hObject, eventdata, handles);
  410. end
  411. %--- Executes on button press in ButtonAddSubjID. ---%
  412. %----------------------------------------------------%
  413. function ButtonAddSubjID_Callback(hObject, eventdata, handles)
  414. if isempty(handles.name.AnatID) || isempty(handles.paths.AnatID)
  415. msgbox('Warning: Create or load AnatID first.', 'Warning:');
  416. return;
  417. end
  418. if isempty(handles.name.CurrentGroupID)
  419. msgbox('Warning: Create or load GroupID first.', 'Warning:');
  420. return;
  421. end
  422. % Reads and set SubjID:
  423. InputSubjID = get(handles.TextboxSubjID, 'String');
  424. InputSubjID = deblank(InputSubjID);
  425. InputSubjID = regexprep(InputSubjID, '\s+', '_');
  426. InputSubjID = cellstr(InputSubjID);
  427. if isempty(InputSubjID{1})
  428. return;
  429. end
  430. if ~isempty(handles.name.SubjID) && ismember(InputSubjID{1}, handles.name.SubjID)
  431. return; % If SubjID already added
  432. end
  433. handles.name.SubjID = [handles.name.SubjID; InputSubjID];
  434. NewIndex = length(handles.name.SubjID);
  435. % Initialize cells for new subject:
  436. handles.paths.AnatFolder {NewIndex} = [];
  437. handles.paths.AnatFile {NewIndex} = [];
  438. handles.paths.AnatFullpath {NewIndex} = [];
  439. handles.paths.PreprocMRI {NewIndex} = [];
  440. handles.gui.Status {NewIndex} = [];
  441. % Update GUI:
  442. handles = UpdateSubjIDSettings (handles);
  443. handles = UpdateInputAnatSettings (handles);
  444. handles = DetectStatus (handles, NewIndex);
  445. handles = UpdateStatusSettings (handles);
  446. handles = UpdatePreprocSettings (handles); % For enable/disable
  447. % Save handles:
  448. set(handles.ListboxSubjID, 'Value', length(handles.name.SubjID));
  449. if ~isempty(handles.paths.AnatFullpath)
  450. set(handles.ListboxInputAnat, 'Value', length(handles.name.SubjID));
  451. end
  452. if ~isempty(handles.gui.Status)
  453. set(handles.ListboxStatus, 'Value', length(handles.name.SubjID));
  454. end
  455. guidata(hObject, handles);
  456. %--- Executes on button press in ButtonRmvSubjID. ---%
  457. %----------------------------------------------------%
  458. function ButtonRmvSubjID_Callback(hObject, eventdata, handles)
  459. if isempty(handles.name.SubjID)
  460. return;
  461. end
  462. SelectedIndex = get(handles.ListboxSubjID, 'Value');
  463. handles.name.SubjID(SelectedIndex) = [];
  464. % Remove data & status cells for removed subject:
  465. handles.paths.AnatFolder (SelectedIndex) = [];
  466. handles.paths.AnatFile (SelectedIndex) = [];
  467. handles.paths.AnatFullpath (SelectedIndex) = [];
  468. handles.paths.PreprocMRI (SelectedIndex) = [];
  469. handles.gui.Status (SelectedIndex) = [];
  470. % Update GUI:
  471. handles = UpdateSubjIDSettings (handles);
  472. handles = UpdateInputAnatSettings (handles);
  473. handles = UpdateStatusSettings (handles);
  474. handles = UpdatePreprocSettings (handles); % For enable/disable
  475. % Save handles:
  476. guidata(hObject, handles);
  477. %--- Updates SubjID settings & GUI panel: ---%
  478. %--------------------------------------------%
  479. function OutputHandles = UpdateSubjIDSettings(InputHandles)
  480. handles = InputHandles;
  481. % Update PreprocMRI paths (Location of FT MRIs to be read in):
  482. for s = 1:length(handles.name.SubjID)
  483. handles.paths.PreprocMRI{s} = ...
  484. [handles.paths.CurrentGroupID,'/',handles.name.SubjID{s},'_PreprocMRI.mat'];
  485. end
  486. % Update listbox:
  487. set(handles.ListboxSubjID, 'String', handles.name.SubjID);
  488. CurrentIndex = get(handles.ListboxSubjID, 'Value');
  489. MaxSubjIndex = length(handles.name.SubjID);
  490. if isempty(CurrentIndex) || CurrentIndex == 0 || CurrentIndex > MaxSubjIndex
  491. set(handles.ListboxSubjID, 'Value', MaxSubjIndex);
  492. set(handles.ListboxInputAnat, 'Value', MaxSubjIndex);
  493. set(handles.ListboxStatus, 'Value', MaxSubjIndex);
  494. end
  495. % Set output handles:
  496. OutputHandles = handles;
  497. %--- Load SubjID settings & GUI panel: ---%
  498. %-----------------------------------------%
  499. function OutputHandles = LoadSubjIDSettings(InputHandles, LoadedMat)
  500. handles = InputHandles;
  501. % Load SubjID and respective PreprocMRI paths:
  502. handles.name.SubjID = LoadedMat.name.SubjID;
  503. handles.paths.PreprocMRI = LoadedMat.paths.PreprocMRI;
  504. % Load GUI:
  505. set(handles.ListboxSubjID, 'String', handles.name.SubjID);
  506. set(handles.ListboxSubjID, 'Value', 1);
  507. handles = UpdatePreprocSettings(handles); % For enable/disable
  508. % Set output handles:
  509. OutputHandles = handles;
  510. %--- Reset SubjID settings & GUI panel: ---%
  511. %------------------------------------------%
  512. function OutputHandles = ResetSubjIDSettings(InputHandles)
  513. handles = InputHandles;
  514. handles.paths.PreprocMRI = [];
  515. handles.name.SubjID = [];
  516. set(handles.ListboxSubjID, 'String', []);
  517. set(handles.ListboxSubjID, 'Value', 1);
  518. % Set output handles:
  519. OutputHandles = handles;
  520. %=============================================%
  521. % FUNCTIONS FOR MRI FILE SELECTION & DISPLAY: %
  522. %=============================================%
  523. %--- Executes on selection change in ListboxInputAnat. ---%
  524. %---------------------------------------------------------%
  525. function ListboxInputAnat_Callback(hObject, eventdata, handles)
  526. SelectedIndex = get(handles.ListboxInputAnat, 'Value');
  527. set(handles.ListboxSubjID, 'Value', SelectedIndex);
  528. set(handles.ListboxStatus, 'Value', SelectedIndex);
  529. handles = UpdatePreprocSettings(handles); % For enable/disable
  530. guidata(hObject, handles);
  531. %--- Updates settings & GUI panel for input MRI files: ---%
  532. %---------------------------------------------------------%
  533. function OutputHandles = UpdateInputAnatSettings(InputHandles)
  534. handles = InputHandles;
  535. % Make sure cells initialized:
  536. for s = 1:length(handles.name.SubjID)
  537. try
  538. handles.paths.AnatFolder{s};
  539. handles.paths.AnatFile{s};
  540. handles.paths.AnatFullpath{s};
  541. catch
  542. handles.paths.AnatFolder{s} = [];
  543. handles.paths.AnatFile{s} = [];
  544. handles.paths.AnatFullpath{s} = [];
  545. end
  546. end
  547. % Update listbox:
  548. set(handles.ListboxInputAnat, 'String', handles.paths.AnatFullpath);
  549. % Set output handles:
  550. OutputHandles = handles;
  551. %--- Load settings & GUI panel for input MRI files: ---%
  552. %------------------------------------------------------%
  553. function OutputHandles = LoadInputAnatSettings(InputHandles, LoadedMat)
  554. handles = InputHandles;
  555. % Load input MRI files:
  556. handles.paths.AnatFolder = LoadedMat.paths.AnatFolder;
  557. handles.paths.AnatFile = LoadedMat.paths.AnatFile;
  558. handles.paths.AnatFullpath = LoadedMat.paths.AnatFullpath;
  559. % Update GUI:
  560. set(handles.ListboxInputAnat, 'String', handles.paths.AnatFullpath);
  561. set(handles.ListboxInputAnat, 'Value', 1);
  562. handles = UpdatePreprocSettings(handles); % For enable/disable
  563. % Set output handles:
  564. OutputHandles = handles;
  565. %--- Reset settings & GUI panel for input MRI files: ---%
  566. %-------------------------------------------------------%
  567. function OutputHandles = ResetInputAnatSettings(InputHandles)
  568. handles = InputHandles;
  569. % Reset input anat:
  570. handles.paths.AnatFolder = [];
  571. handles.paths.AnatFile = [];
  572. handles.paths.AnatFullpath = [];
  573. for s = 1:length(handles.name.SubjID)
  574. handles.paths.AnatFolder{s} = [];
  575. handles.paths.AnatFile{s} = [];
  576. handles.paths.AnatFullpath{s} = [];
  577. end
  578. % Reset GUI panel:
  579. set(handles.ListboxInputAnat, 'String', []);
  580. set(handles.ListboxInputAnat, 'Value', 1);
  581. % Set output handles:
  582. OutputHandles = handles;
  583. %===============================%
  584. % FUNCTIONS FOR STATUS UPDATES: %
  585. %===============================%
  586. %--- Executes on selection change in ListboxStatus. ---%
  587. %------------------------------------------------------%
  588. function ListboxStatus_Callback(hObject, eventdata, handles)
  589. SelectedIndex = get(handles.ListboxStatus, 'Value');
  590. set(handles.ListboxSubjID, 'Value', SelectedIndex);
  591. set(handles.ListboxInputAnat, 'Value', SelectedIndex);
  592. handles = UpdatePreprocSettings(handles); % For enable/disable
  593. guidata(hObject, handles);
  594. %--- Executes on button press in ButtonRefreshStatus. ---%
  595. %--------------------------------------------------------%
  596. function ButtonRefreshStatus_Callback(hObject, eventdata, handles)
  597. StatusWaitbar = waitbar(0, ...
  598. 'Please wait. Loading files from session.', 'Windowstyle', 'modal');
  599. for s = 1:length(handles.name.SubjID)
  600. waitbar(s/length(handles.name.SubjID), StatusWaitbar);
  601. handles = DetectStatus(handles, s);
  602. end
  603. delete(StatusWaitbar)
  604. handles = UpdateStatusSettings(handles);
  605. guidata(hObject, handles);
  606. %--- Function to acquire status: ---%
  607. %-----------------------------------%
  608. function OutputHandles = DetectStatus(InputHandles, SubjIndex)
  609. handles = InputHandles;
  610. % Get selected subject and update status.
  611. % Unlike PreprocMEG, only selected subject gets worked on, so
  612. % update on a subject-by-subject basis for efficiency.
  613. s = SubjIndex;
  614. % Check if MRI file has been selected:
  615. if isempty(handles.paths.AnatFullpath{s})
  616. handles.gui.Status{s} = 'Select MRI file to load into FT.';
  617. else
  618. handles.gui.Status{s} = [];
  619. end
  620. % Check if read into FT and coregistration:
  621. if exist(handles.paths.PreprocMRI{s}, 'file')
  622. MRIdata = LoadFTmat(handles.paths.PreprocMRI{s}, 'PreprocMRI');
  623. if isempty(MRIdata)
  624. handles.gui.Status{s} = 'FT file detected, but could not be read. See ErrorLog.';
  625. else
  626. DimStr = num2str(MRIdata.dim);
  627. if isfield(MRIdata, 'coordsys')
  628. Coordsys = num2str(MRIdata.coordsys);
  629. handles.gui.Status{s} = ...
  630. ['FT file detected. Coordsys: ',Coordsys,'. Dims: ',DimStr];
  631. else
  632. handles.gui.Status{s} = ...
  633. ['FT file detected. No Coordsys found. Dims: ',DimStr];
  634. end
  635. end
  636. end
  637. % Save as output:
  638. OutputHandles = handles;
  639. %--- Update status settings & GUI panel: ---%
  640. %-------------------------------------------%
  641. function OutputHandles = UpdateStatusSettings(InputHandles)
  642. handles = InputHandles;
  643. % Make sure cells initialized:
  644. for s = 1:length(handles.name.SubjID)
  645. try
  646. handles.gui.Status{s};
  647. catch
  648. handles.gui.Status{s} = [];
  649. end
  650. end
  651. % Update listbox:
  652. set(handles.ListboxStatus, 'String', handles.gui.Status);
  653. % Set output handles:
  654. OutputHandles = handles;
  655. %--- Reset status settings & GUI panel: ---%
  656. %------------------------------------------%
  657. function OutputHandles = ResetStatusSettings(InputHandles)
  658. handles = InputHandles;
  659. % Reset status:
  660. handles.gui.Status = [];
  661. for s = 1:length(handles.name.SubjID)
  662. handles.gui.Status{s} = [];
  663. end
  664. % Reset GUI status panel:
  665. set(handles.ListboxStatus, 'String', []);
  666. set(handles.ListboxStatus, 'Value', 1);
  667. % Set output handles:
  668. OutputHandles = handles;
  669. %===============================================%
  670. % FUNCTIONS FOR SAVING & LOADING PREPROC INPUT: %
  671. %===============================================%
  672. %--- Executes on button press in ButtonSaveInput. ---%
  673. %----------------------------------------------------%
  674. function ButtonSaveInput_Callback(hObject, eventdata, handles)
  675. if isempty(handles.paths.Rootpath)
  676. msgbox('Warning: Select root directory first.', 'Warning:');
  677. return;
  678. end
  679. if isempty(handles.name.AnatID) || isempty(handles.paths.AnatID)
  680. msgbox('Warning: Create or load AnatID first.', 'Warning:');
  681. return;
  682. end
  683. if isempty(handles.name.CurrentGroupID)
  684. msgbox('Warning: Create or load GroupID first.', 'Warning:');
  685. return;
  686. end
  687. if isempty(handles.name.SubjID) || isempty(handles.paths.PreprocMRI)
  688. msgbox('Warning: Need to specify SubjIDs.', 'Warning:');
  689. return;
  690. end
  691. if isempty(handles.paths.AnatFullpath)
  692. msgbox('Warning: MRI files have not been read into FT yet.', 'Warning:')
  693. return;
  694. end
  695. % Make sure Rootpath & AnatID don't have spaces (will cause issues for AFNI later):
  696. CheckSpaces1 = strfind(handles.paths.Rootpath, ' ');
  697. CheckSpaces2 = strfind(handles.paths.AnatID, ' ');
  698. if ~isempty(CheckSpaces1) || ~isempty(CheckSpaces2)
  699. message = {'Error: Target directory or AnatID contains spaces.';
  700. 'AFNI functions cannot read folder & file paths with spaces.';
  701. 'AFNI functions are required for file conversions later on.'};
  702. msgbox(message, 'Error:')
  703. return;
  704. end
  705. % Check save path:
  706. PreprocInputMat = [handles.paths.CurrentGroupID,...
  707. '/PreprocInputMRI_',handles.name.CurrentGroupID,'.mat'];
  708. if exist(PreprocInputMat, 'file')
  709. prompt = {'WARNING:';
  710. 'PreprocInputMRI .mat already exists for this GroupID.';
  711. 'Do you wish to continue and overwrite it?'};
  712. OverwriteMat = questdlg(prompt, 'WARNING:', 'YES', 'NO', 'NO');
  713. if strcmp(OverwriteMat, 'NO')
  714. return;
  715. else
  716. delete(PreprocInputMat);
  717. end
  718. end
  719. % Save input parameters for current GroupID:
  720. name = handles.name;
  721. paths = handles.paths;
  722. paths = rmfield(paths, 'Rootpath'); % Rmv GUI only paths that aren't in load fcns.
  723. paths = rmfield(paths, 'AnatID'); % - These paths auto-adapt if folders moved.
  724. paths = rmfield(paths, 'CurrentGroupID');
  725. CheckSavePath(PreprocInputMat, 'PreprocMRI');
  726. save(PreprocInputMat, 'name', 'paths');
  727. % Feedback:
  728. if exist(PreprocInputMat, 'file')
  729. msgbox('Current input parameters successfully saved.')
  730. else
  731. msgbox('Error: Failed to save input parameters.')
  732. end
  733. %--- Executes on button press in ButtonLoadInput. ---%
  734. %----------------------------------------------------%
  735. function ButtonLoadInput_Callback(hObject, eventdata, handles)
  736. if isempty(handles.paths.Rootpath)
  737. msgbox('Warning: Select root directory first.', 'Warning:');
  738. return;
  739. end
  740. if isempty(handles.name.AnatID) || isempty(handles.paths.AnatID)
  741. msgbox('Warning: Create or load AnatID first.', 'Warning:');
  742. return;
  743. end
  744. if isempty(handles.name.CurrentGroupID)
  745. msgbox('Warning: Create or load GroupID first.', 'Warning:');
  746. return;
  747. end
  748. [matfile, matpath] = uigetfile([handles.paths.CurrentGroupID,...
  749. '/PreprocInputMRI_*.mat'], 'Select PreprocInputMRI .mat:', 'MultiSelect', 'off');
  750. if matfile == 0
  751. msgbox('Note: Load cancelled. File not selected.', 'Note:');
  752. return;
  753. end
  754. % Reset settings & GUI panels:
  755. handles = ResetSubjIDSettings (handles);
  756. handles = ResetInputAnatSettings (handles);
  757. handles = ResetStatusSettings (handles);
  758. handles = ResetPreprocSettings (handles);
  759. % Load input settings:
  760. LoadedMat = load([matpath,matfile]);
  761. handles = LoadSubjIDSettings (handles, LoadedMat);
  762. handles = LoadInputAnatSettings (handles, LoadedMat);
  763. % Update settings & GUI panels (to enable/disable):
  764. handles = UpdateSubjIDSettings (handles);
  765. handles = UpdateInputAnatSettings (handles);
  766. handles = UpdatePreprocSettings (handles);
  767. % Update status for all loaded subjects:
  768. StatusWaitbar = waitbar(0, ...
  769. 'Please wait. Loading files from session.', 'Windowstyle', 'modal');
  770. for s = 1:length(handles.name.SubjID)
  771. waitbar(s/length(handles.name.SubjID), StatusWaitbar);
  772. handles = DetectStatus(handles, s);
  773. end
  774. delete(StatusWaitbar)
  775. handles = UpdateStatusSettings(handles);
  776. % Save handles:
  777. guidata(hObject, handles);
  778. %======================================%
  779. % FUNCTIONS TO READ IN & PROCESS MRIs: %
  780. %======================================%
  781. %--- Executes on button press in ButtonReadMRItoFT. ---%
  782. %------------------------------------------------------%
  783. function ButtonReadMRItoFT_Callback(hObject, eventdata, handles)
  784. if isempty(handles.name.AnatID) || isempty(handles.paths.AnatID)
  785. msgbox('Warning: Create or load AnatID first.', 'Warning:');
  786. return;
  787. end
  788. if isempty(handles.name.CurrentGroupID)
  789. msgbox('Warning: Create or load GroupID first.', 'Warning:');
  790. return;
  791. end
  792. if isempty(handles.name.SubjID)
  793. msgbox('Warning: Add SubjID first.', 'Warning:');
  794. return;
  795. end
  796. % Make sure Rootpath & AnatID don't have spaces (will cause issues for AFNI later):
  797. CheckSpaces1 = strfind(handles.paths.Rootpath, ' ');
  798. CheckSpaces2 = strfind(handles.paths.AnatID, ' ');
  799. if ~isempty(CheckSpaces1) || ~isempty(CheckSpaces2)
  800. message = {'Error: Target directory or AnatID contains spaces.';
  801. 'AFNI functions cannot read folder & file paths with spaces.';
  802. 'AFNI functions are required for file conversions later on.'};
  803. msgbox(message, 'Error:')
  804. return;
  805. end
  806. % Check for existing files:
  807. SubjIndex = get(handles.ListboxSubjID, 'Value');
  808. if exist(handles.paths.PreprocMRI{SubjIndex}, 'file')
  809. prompt = {'Warning: PreprocMRI already exists for this SubjID.';
  810. 'Do you wish to continue and overwrite?'};
  811. Overwrite = questdlg(prompt, 'WARNING:', 'YES', 'NO', 'NO');
  812. if strcmp(Overwrite, 'NO')
  813. return;
  814. end
  815. end
  816. % Select raw MRI file and read into FT:
  817. [File, Folder] = uigetfile([handles.paths.Rootpath,'/*']);
  818. if File == 0
  819. return; % If user cancels
  820. end
  821. WaitBox = StartWaitBox('READING MRI FILE INTO FT:');
  822. MRIdata = ft_read_mri([Folder,File])
  823. close(WaitBox);
  824. CheckSavePath(handles.paths.PreprocMRI{SubjIndex}, 'PreprocMRI');
  825. save(handles.paths.PreprocMRI{SubjIndex}, 'MRIdata');
  826. handles.paths.AnatFolder {SubjIndex} = Folder;
  827. handles.paths.AnatFile {SubjIndex} = File;
  828. handles.paths.AnatFullpath {SubjIndex} = [Folder,File];
  829. % Update GUI:
  830. handles = UpdateInputAnatSettings (handles);
  831. handles = UpdatePreprocSettings (handles);
  832. handles = DetectStatus (handles, SubjIndex);
  833. handles = UpdateStatusSettings (handles);
  834. % Save handles:
  835. guidata(hObject, handles);
  836. %--- Executes on button press in ButtonClearMRI. ---%
  837. %---------------------------------------------------%
  838. function ButtonClearMRI_Callback(hObject, eventdata, handles)
  839. if isempty(handles.name.SubjID)
  840. return;
  841. end
  842. % Remove FT MRI file for selected SubjID:
  843. SubjIndex = get(handles.ListboxSubjID, 'Value');
  844. if exist(handles.paths.PreprocMRI{SubjIndex}, 'file')
  845. delete(handles.paths.PreprocMRI{SubjIndex});
  846. end
  847. if ~isempty(handles.paths.AnatFullpath)
  848. handles.paths.AnatFolder {SubjIndex} = [];
  849. handles.paths.AnatFile {SubjIndex} = [];
  850. handles.paths.AnatFullpath {SubjIndex} = [];
  851. end
  852. % Update GUI:
  853. handles = UpdateInputAnatSettings (handles);
  854. handles = UpdatePreprocSettings (handles);
  855. handles = DetectStatus (handles, SubjIndex);
  856. handles = UpdateStatusSettings (handles);
  857. % Save handles:
  858. guidata(hObject, handles);
  859. %--- Executes on button press in ButtonCheckTransformHand. ---%
  860. %-------------------------------------------------------------%
  861. function ButtonCheckTransformHand_Callback(hObject, eventdata, handles)
  862. if isempty(handles.name.SubjID) || isempty(handles.paths.PreprocMRI)
  863. msgbox('Warning: Add and select SubjID first.', 'Warning:')
  864. return;
  865. end
  866. % Load MRI file:
  867. SubjIndex = get(handles.ListboxSubjID, 'Value');
  868. if ~exist(handles.paths.PreprocMRI{SubjIndex}, 'file')
  869. msgbox('Warning: MRI file for SubjID has not been read into FT yet.', 'Warning:')
  870. return;
  871. end
  872. MRIdata = LoadFTmat(handles.paths.PreprocMRI{SubjIndex}, 'PreprocMRI');
  873. if isempty(MRIdata)
  874. msgbox('Error: Failed to load PreprocMRI file for SubjID. See ErrorLog.', 'Error:')
  875. return;
  876. end
  877. % Check handedness of transformation matrix:
  878. temp = det(MRIdata.transform(1:3, 1:3));
  879. if temp < 0
  880. message = {'Transformation matrix is left-handed.';
  881. 'If +XYZ is also right-handed, viewer shows radiological view.'};
  882. msgbox(message);
  883. else
  884. message = {'Transformation matrix is right-handed.';
  885. 'If +XYZ is also right-handed, viewer shows neurological view.'};
  886. msgbox(message);
  887. end
  888. %--- Executes on selection change in DropdownCoordsys. ---%
  889. %---------------------------------------------------------%
  890. function DropdownCoordsys_Callback(hObject, eventdata, handles)
  891. % Note: By default, if cfg.coordsys is not specified for ft_volumerealign,
  892. % the output coordinate system will always default to "ctf" or "spm".
  893. % User specifies desired coordinate system here to fill in cfg.coordsys field.
  894. guidata(hObject, handles);
  895. %--- Executes on button press in ButtonCoregisterMRI. ---%
  896. %--------------------------------------------------------%
  897. function ButtonCoregisterMRI_Callback(hObject, eventdata, handles)
  898. if isempty(handles.name.SubjID) || isempty(handles.paths.PreprocMRI)
  899. msgbox('Warning: Add and select SubjID first.', 'Warning:')
  900. return;
  901. end
  902. % Load MRI file:
  903. SubjIndex = get(handles.ListboxSubjID, 'Value');
  904. if ~exist(handles.paths.PreprocMRI{SubjIndex}, 'file')
  905. msgbox('Warning: MRI file for SubjID has not been read into FT yet.', 'Warning:')
  906. return;
  907. end
  908. MRIdata = LoadFTmat(handles.paths.PreprocMRI{SubjIndex}, 'PreprocMRI');
  909. if isempty(MRIdata)
  910. msgbox('Error: Failed to load PreprocMRI file for SubjID. See ErrorLog.', 'Error:')
  911. return;
  912. end
  913. % Check for coordsys (coregistration):
  914. if isfield(MRIdata, 'coordsys')
  915. prompt = {'WARNING:'; '';
  916. 'Field "coordsys" detected. MRI may already be coregistered.';
  917. 'If so, it is recommended you DO NOT coregister again.'; '';
  918. 'If you wish to redo the coregistration, go back and click the';
  919. '"Clear Subj FT MRI" button first.'; '';
  920. 'Do you wish to continue and run coregistration again?'; ''};
  921. RunCoreg = questdlg(prompt, 'WARNING:', 'YES', 'NO', 'NO');
  922. if strcmp(RunCoreg, 'NO')
  923. return;
  924. end
  925. end
  926. % Show instructions:
  927. if handles.gui.ShowInstruct == 1;
  928. Instructions = {'----------------------------';
  929. 'COREGISTRATION INSTRUCTIONS:';
  930. '----------------------------'; '';
  931. 'NOTE:';
  932. 'If the crosshair does not appear, push "C" to toggle its visibility.'; ''; '';
  933. 'IMPORTANT:';
  934. ' Push "F" to toggle FIDUCIAL & LANDMARK visibility: When you place';
  935. ' fiducials and landmarks, they should appear as coloured circles.'; ''; '';
  936. 'If placing FIDUCIALS (ex: for CTF):';
  937. ' 1) Push "F" to toggle fiducial visibility if it is not on.';
  938. ' 2) Place fiducials with keys: "L" (left), "R" (right), and "N" (nasion).';
  939. ' 3) Set extra Z-point in positive Z-coordinates using "Z" (see below).';
  940. ' 4) Once finished, push "Q" to save the coregistration.'; '';
  941. ' In most cases, Z-point can normally be placed at the top-of-head.';
  942. ' Additional Z-point ensures left & right fiducials are not flipped.';
  943. ' Note: Only works with MRI formats supported by Fieldtrip.'; ''; '';
  944. 'If placing LANDMARKS (ex: for SPM):';
  945. ' 1) Place landmarks with keys: "A", "P", and "Z".';
  946. ' 2) Once finished, push "Q" to save the coregistration.'; ''; ''; ''};
  947. Show = questdlg(Instructions, 'INSTRUCTIONS:', 'OK', 'Don''t show again', 'OK');
  948. if strcmp(Show, 'Don''t show again')
  949. handles.gui.ShowInstruct = 0;
  950. end
  951. end
  952. % Get target coordinate system from coordsys dropdown:
  953. % Note: Defaults to "ctf" or "spm" if cfg.coordsys is left empty.
  954. DropdownOptions = get(handles.DropdownCoordsys, 'String');
  955. CoregCoordsys = DropdownOptions{get(handles.DropdownCoordsys, 'Value')};
  956. ViableOptions = {'ctf', 'spm', 'tal', '4d', 'yokogawa', 'neuromag', 'itab'};
  957. if ismember(CoregCoordsys, ViableOptions)
  958. cfgRealign.coordsys = CoregCoordsys;
  959. else
  960. error('Unrecognized Option.'); % error-check
  961. end
  962. % Coregister anatomy:
  963. cfgRealign.method = 'interactive';
  964. cfgRealign.parameter = 'anatomy';
  965. MRIdata = ft_volumerealign(cfgRealign, MRIdata);
  966. CheckSavePath(handles.paths.PreprocMRI{SubjIndex}, 'PreprocMRI');
  967. save(handles.paths.PreprocMRI{SubjIndex}, 'MRIdata');
  968. % Update GUI:
  969. handles = DetectStatus (handles, SubjIndex);
  970. handles = UpdateStatusSettings (handles);
  971. % Save handles:
  972. guidata(hObject, handles);
  973. %--- Executes on button press in ButtonCheckCoordsys. ---%
  974. %--------------------------------------------------------%
  975. function ButtonCheckCoordsys_Callback(hObject, eventdata, handles)
  976. if isempty(handles.name.SubjID) || isempty(handles.paths.PreprocMRI)
  977. msgbox('Warning: Add and select SubjID first.', 'Warning:')
  978. return;
  979. end
  980. % Load MRI file:
  981. SubjIndex = get(handles.ListboxSubjID, 'Value');
  982. if ~exist(handles.paths.PreprocMRI{SubjIndex}, 'file')
  983. msgbox('Warning: MRI file for SubjID has not been read into FT yet.', 'Warning:')
  984. return;
  985. end
  986. MRIdata = LoadFTmat(handles.paths.PreprocMRI{SubjIndex}, 'PreprocMRI');
  987. if isempty(MRIdata)
  988. msgbox('Error: Failed to load PreprocMRI file for SubjID. See ErrorLog.', 'Error:')
  989. return;
  990. end
  991. % Check coregistration:
  992. ft_determine_coordsys(MRIdata, 'interactive', 'no');
  993. %--- Executes on button press in ButtonPlotMRI. ---%
  994. %--------------------------------------------------%
  995. function ButtonPlotMRI_Callback(hObject, eventdata, handles)
  996. if isempty(handles.name.SubjID) || isempty(handles.paths.PreprocMRI)
  997. msgbox('Warning: Add and select SubjID first.', 'Warning:')
  998. return;
  999. end
  1000. % Load MRI file:
  1001. SubjIndex = get(handles.ListboxSubjID, 'Value');
  1002. if ~exist(handles.paths.PreprocMRI{SubjIndex}, 'file')
  1003. msgbox('Warning: MRI file for SubjID has not been read into FT yet.', 'Warning:')
  1004. return;
  1005. end
  1006. CheckInput = CheckPipelineMat(handles.paths.PreprocMRI{SubjIndex}, 'PreprocMRI');
  1007. if CheckInput == 0
  1008. msgbox('Error: Failed to load PreprocMRI file for SubjID. See ErrorLog.', 'Error:')
  1009. return;
  1010. end
  1011. % Plot MRI in ortho view:
  1012. cfgPlot.method = 'ortho';
  1013. cfgPlot.anaparameter = 'anatomy';
  1014. cfgPlot.location = 'center';
  1015. cfgPlot.crosshair = 'yes';
  1016. cfgPlot.interactive = 'no';
  1017. cfgPlot.axis = 'on';
  1018. cfgPlot.inputfile = handles.paths.PreprocMRI{SubjIndex};
  1019. ft_sourceplot(cfgPlot);
  1020. %--- Executes on button press in ButtonResliceMRI. ---%
  1021. %-----------------------------------------------------%
  1022. function ButtonResliceMRI_Callback(hObject, eventdata, handles)
  1023. if isempty(handles.name.SubjID) || isempty(handles.paths.PreprocMRI)
  1024. msgbox('Warning: Add and select SubjID first.', 'Warning:')
  1025. return;
  1026. end
  1027. % Check for required inputs:
  1028. FTcfg = handles.FTcfg;
  1029. if isempty(FTcfg.Reslice.resolution)
  1030. msgbox('Warning: Specify resolution in physical units for resliced MRI.');
  1031. return;
  1032. end
  1033. if get(handles.ButtonResliceCustomRange, 'Value') == 1
  1034. if isempty(FTcfg.Reslice.xrange) || ...
  1035. isempty(FTcfg.Reslice.yrange) || isempty(FTcfg.Reslice.zrange)
  1036. msgbox('Warning: XYZ ranges not specified.');
  1037. return;
  1038. end
  1039. XRange = str2num(get(handles.TextboxResliceXRange, 'String'));
  1040. if ~isequal(size(XRange), [1 2]) || (XRange(1) > XRange(2))
  1041. set(handles.TextboxResliceXRange, 'String', []);
  1042. msgbox('Error: X-range should be: [min max] physical units.', 'Error:')
  1043. return;
  1044. end
  1045. YRange = str2num(get(handles.TextboxResliceYRange, 'String'));
  1046. if ~isequal(size(YRange), [1 2]) || (YRange(1) > YRange(2))
  1047. set(handles.TextboxResliceYRange, 'String', []);
  1048. msgbox('Error: Y-range should be: [min max] physical units.', 'Error:')
  1049. return;
  1050. end
  1051. ZRange = str2num(get(handles.TextboxResliceZRange, 'String'));
  1052. if ~isequal(size(ZRange), [1 2]) || (ZRange(1) > ZRange(2))
  1053. set(handles.TextboxResliceZRange, 'String', []);
  1054. msgbox('Error: Z-range should be: [min max] physical units.', 'Error:')
  1055. return;
  1056. end
  1057. end
  1058. if get(handles.ButtonResliceCustomDims, 'Value') == 1 && isempty(FTcfg.Reslice.dim)
  1059. msgbox('Warning: Custom dimensions not specified.');
  1060. return;
  1061. end
  1062. % Load selected MRI file:
  1063. SubjIndex = get(handles.ListboxSubjID, 'Value');
  1064. if ~exist(handles.paths.PreprocMRI{SubjIndex}, 'file')
  1065. msgbox('Warning: MRI file for SubjID has not been read into FT yet.', 'Warning:')
  1066. return;
  1067. end
  1068. MRIdata = LoadFTmat(handles.paths.PreprocMRI{SubjIndex}, 'PreprocMRI');
  1069. if isempty(MRIdata)
  1070. msgbox('Error: Failed to load PreprocMRI file for SubjID. See ErrorLog.', 'Error:')
  1071. return;
  1072. end
  1073. % Reslice MRI:
  1074. WaitBox = StartWaitBox('RESLICING MRI:');
  1075. MRIdata = ft_volumereslice(FTcfg.Reslice, MRIdata);
  1076. close(WaitBox);
  1077. % Plot resliced MRI for user to check:
  1078. cfgPlot.method = 'ortho';
  1079. cfgPlot.anaparameter = 'anatomy';
  1080. cfgPlot.location = 'center';
  1081. cfgPlot.crosshair = 'yes';
  1082. cfgPlot.interactive = 'no';
  1083. cfgPlot.axis = 'on';
  1084. ft_sourceplot(cfgPlot, MRIdata);
  1085. % Ask user if resliced MRI should be saved:
  1086. KeepReslice = questdlg('Keep resliced MRI or revert back to previous?', ...
  1087. 'SAVE RESLICE?', 'KEEP', 'REVERT', 'REVERT');
  1088. if strcmp(KeepReslice, 'KEEP')
  1089. close(1);
  1090. CheckSavePath(handles.paths.PreprocMRI{SubjIndex}, 'PreprocMRI');
  1091. save(handles.paths.PreprocMRI{SubjIndex}, 'MRIdata');
  1092. else
  1093. close(1);
  1094. return;
  1095. end
  1096. % Update GUI:
  1097. handles = DetectStatus (handles, SubjIndex);
  1098. handles = UpdateStatusSettings (handles);
  1099. % Save handles:
  1100. guidata(hObject, handles);
  1101. %--- Executes when selected object is changed in PanelResliceMRISettings. ---%
  1102. %----------------------------------------------------------------------------%
  1103. function PanelResliceMRISettings_SelectionChangeFcn(hObject, eventdata, handles)
  1104. handles = UpdatePreprocSettings(handles);
  1105. guidata(hObject, handles);
  1106. %--- User enters X-range for reslice here: ---%
  1107. %---------------------------------------------%
  1108. function TextboxResliceXRange_Callback(hObject, eventdata, handles)
  1109. handles = UpdatePreprocSettings(handles);
  1110. guidata(hObject, handles);
  1111. %--- User enters Y-range for reslice here: ---%
  1112. %---------------------------------------------%
  1113. function TextboxResliceYRange_Callback(hObject, eventdata, handles)
  1114. handles = UpdatePreprocSettings(handles);
  1115. guidata(hObject, handles);
  1116. %--- User enters Z-range for reslice here: ---%
  1117. %---------------------------------------------%
  1118. function TextboxResliceZRange_Callback(hObject, eventdata, handles)
  1119. handles = UpdatePreprocSettings(handles);
  1120. guidata(hObject, handles);
  1121. %--- User enters custom volume dimensions for reslice here: ---%
  1122. %--------------------------------------------------------------%
  1123. function TextboxResliceCustomDims_Callback(hObject, eventdata, handles)
  1124. ResliceDims = str2num(get(handles.TextboxResliceCustomDims, 'String'));
  1125. if ~isequal(size(ResliceDims), [1 3])
  1126. set(handles.TextboxResliceCustomDims, 'String', '256, 256, 256');
  1127. msgbox('Error: Dim. of volume should be specified as: [nx, ny, nz].', 'Error:')
  1128. return;
  1129. end
  1130. handles = UpdatePreprocSettings(handles);
  1131. guidata(hObject, handles);
  1132. %--- User enters resolution for reslice here (physical units): ---%
  1133. %-----------------------------------------------------------------%
  1134. function TextboxResliceRes_Callback(hObject, eventdata, handles)
  1135. prompt = {'WARNING:';
  1136. 'Are you sure you wish to change resolution of MRI?';
  1137. 'Should not change resolution unless required.'};
  1138. ChangeRes = questdlg(prompt, 'WARNING:', 'YES', 'NO', 'NO');
  1139. if strcmp(ChangeRes, 'NO')
  1140. set(handles.TextboxResliceRes, 'String', '1');
  1141. return;
  1142. end
  1143. ResliceRes = str2num(get(handles.TextboxResliceRes, 'String'));
  1144. if ~isequal(size(ResliceRes), [1 1])
  1145. set(handles.TextboxResliceRes, 'String', '1');
  1146. msgbox('Error: Resolution should be single # in physical units.', 'Error:')
  1147. return;
  1148. end
  1149. handles = UpdatePreprocSettings(handles);
  1150. guidata(hObject, handles);
  1151. %--- Updates PreprocMRI settings & GUI panel: ---%
  1152. %------------------------------------------------%
  1153. function OutputHandles = UpdatePreprocSettings(InputHandles)
  1154. handles = InputHandles;
  1155. FTcfg = handles.FTcfg;
  1156. % Update reslice settings:
  1157. FTcfg.Reslice = [];
  1158. FTcfg.Reslice.resolution = str2num(get(handles.TextboxResliceRes, 'String'));
  1159. if get(handles.ButtonResliceCustomDims, 'Value') == 1
  1160. FTcfg.Reslice.dim = str2num(get(handles.TextboxResliceCustomDims, 'String'));
  1161. elseif get(handles.ButtonResliceCustomRange, 'Value') == 1
  1162. FTcfg.Reslice.xrange = str2num(get(handles.TextboxResliceXRange, 'String'));
  1163. FTcfg.Reslice.yrange = str2num(get(handles.TextboxResliceYRange, 'String'));
  1164. FTcfg.Reslice.zrange = str2num(get(handles.TextboxResliceZRange, 'String'));
  1165. end
  1166. % Enable/Disable GUI components:
  1167. set(handles.ButtonReadMRItoFT, 'Enable', 'on');
  1168. set(handles.ButtonClearMRI, 'Enable', 'on');
  1169. set(handles.ButtonCheckTransformHand, 'Enable', 'on');
  1170. set(handles.ButtonCoregisterMRI, 'Enable', 'on');
  1171. set(handles.ButtonCheckCoordsys, 'Enable', 'on');
  1172. set(handles.ButtonPlotMRI, 'Enable', 'on');
  1173. set(handles.ButtonResliceMRI, 'Enable', 'on');
  1174. set(findall(handles.PanelResliceMRISettings, '-property', 'Enable'), 'Enable', 'on');
  1175. SubjIndex = get(handles.ListboxSubjID, 'Value');
  1176. if isempty(handles.paths.PreprocMRI) || ~exist(handles.paths.PreprocMRI{SubjIndex}, 'file')
  1177. set(handles.ButtonClearMRI, 'Enable', 'off');
  1178. set(handles.ButtonCheckTransformHand, 'Enable', 'off');
  1179. set(handles.ButtonCoregisterMRI, 'Enable', 'off');
  1180. set(handles.ButtonCheckCoordsys, 'Enable', 'off');
  1181. set(handles.ButtonPlotMRI, 'Enable', 'off');
  1182. set(handles.ButtonResliceMRI, 'Enable', 'off');
  1183. set(findall(handles.PanelResliceMRISettings, '-property', 'Enable'), 'Enable', 'off');
  1184. end
  1185. if get(handles.ButtonResliceDefaultDims, 'Value') == 1
  1186. set(handles.TextboxResliceXRange, 'Enable', 'off');
  1187. set(handles.TextboxResliceYRange, 'Enable', 'off');
  1188. set(handles.TextboxResliceZRange, 'Enable', 'off');
  1189. set(handles.TextboxResliceCustomDims, 'Enable', 'off');
  1190. set(handles.TextXRange, 'Enable', 'off');
  1191. set(handles.TextYRange, 'Enable', 'off');
  1192. set(handles.TextZRange, 'Enable', 'off');
  1193. set(handles.TextResliceCustomDims, 'Enable', 'off');
  1194. elseif get(handles.ButtonResliceCustomDims, 'Value') == 1
  1195. set(handles.TextboxResliceXRange, 'Enable', 'off');
  1196. set(handles.TextboxResliceYRange, 'Enable', 'off');
  1197. set(handles.TextboxResliceZRange, 'Enable', 'off');
  1198. set(handles.TextXRange, 'Enable', 'off');
  1199. set(handles.TextYRange, 'Enable', 'off');
  1200. set(handles.TextZRange, 'Enable', 'off');
  1201. elseif get(handles.ButtonResliceCustomRange, 'Value') == 1
  1202. set(handles.TextboxResliceCustomDims, 'Enable', 'off');
  1203. set(handles.TextResliceCustomDims, 'Enable', 'off');
  1204. end
  1205. % Set output handles:
  1206. handles.FTcfg = FTcfg;
  1207. OutputHandles = handles;
  1208. %--- Reset PreprocMRI settings % GUI panel: ---%
  1209. %----------------------------------------------%
  1210. function OutputHandles = ResetPreprocSettings(InputHandles)
  1211. handles = InputHandles;
  1212. % Reset GUI reslice:
  1213. set(handles.ButtonResliceDefaultDims, 'Value', 1);
  1214. set(handles.TextboxResliceXRange, 'String', []);
  1215. set(handles.TextboxResliceYRange, 'String', []);
  1216. set(handles.TextboxResliceZRange, 'String', []);
  1217. set(handles.TextboxResliceCustomDims, 'String', '256, 256, 256');
  1218. set(handles.TextboxResliceRes, 'String', '1');
  1219. % Set output handles:
  1220. OutputHandles = handles;
  1221. %=================================%
  1222. % FUNCTION TO OPEN MODAL WAITBOX: %
  1223. %=================================%
  1224. function WaitBox = StartWaitBox(TextString)
  1225. WaitBox = dialog('Units', 'pixels', 'Position', [500 500 300 40],...
  1226. 'Windowstyle', 'modal', 'NextPlot', 'new', 'Name', 'Please Wait:');
  1227. uicontrol('Parent', WaitBox, 'Units', 'pixels', 'Position', [20 10 250 20],...
  1228. 'Style', 'text', 'String', TextString, 'FontWeight', 'bold');
  1229. movegui(WaitBox, 'center');
  1230. %============================%
  1231. % GUIDE CREATEFCN FUNCTIONS: %
  1232. %============================%
  1233. % --- Executes during object creation, after setting all properties.
  1234. function TextboxRootpath_CreateFcn(hObject, eventdata, handles)
  1235. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1236. set(hObject,'BackgroundColor','white');
  1237. end
  1238. % --- Executes during object creation, after setting all properties.
  1239. function TextboxAnatID_CreateFcn(hObject, eventdata, handles)
  1240. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1241. set(hObject,'BackgroundColor','white');
  1242. end
  1243. % --- Executes during object creation, after setting all properties.
  1244. function TextboxGroupID_CreateFcn(hObject, eventdata, handles)
  1245. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1246. set(hObject,'BackgroundColor','white');
  1247. end
  1248. % --- Executes during object creation, after setting all properties.
  1249. function ListboxSubjID_CreateFcn(hObject, eventdata, handles)
  1250. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1251. set(hObject,'BackgroundColor','white');
  1252. end
  1253. % --- Executes during object creation, after setting all properties.
  1254. function TextboxSubjID_CreateFcn(hObject, eventdata, handles)
  1255. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1256. set(hObject,'BackgroundColor','white');
  1257. end
  1258. % --- Executes during object creation, after setting all properties.
  1259. function ListboxInputAnat_CreateFcn(hObject, eventdata, handles)
  1260. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1261. set(hObject,'BackgroundColor','white');
  1262. end
  1263. % --- Executes during object creation, after setting all properties.
  1264. function ListboxStatus_CreateFcn(hObject, eventdata, handles)
  1265. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1266. set(hObject,'BackgroundColor','white');
  1267. end
  1268. % --- Executes during object creation, after setting all properties.
  1269. function DropdownCoordsys_CreateFcn(hObject, eventdata, handles)
  1270. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1271. set(hObject,'BackgroundColor','white');
  1272. end
  1273. % --- Executes during object creation, after setting all properties.
  1274. function TextboxResliceRes_CreateFcn(hObject, eventdata, handles)
  1275. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1276. set(hObject,'BackgroundColor','white');
  1277. end
  1278. % --- Executes during object creation, after setting all properties.
  1279. function TextboxResliceCustomDims_CreateFcn(hObject, eventdata, handles)
  1280. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1281. set(hObject,'BackgroundColor','white');
  1282. end
  1283. % --- Executes during object creation, after setting all properties.
  1284. function TextboxResliceXRange_CreateFcn(hObject, eventdata, handles)
  1285. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1286. set(hObject,'BackgroundColor','white');
  1287. end
  1288. % --- Executes during object creation, after setting all properties.
  1289. function TextboxResliceYRange_CreateFcn(hObject, eventdata, handles)
  1290. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1291. set(hObject,'BackgroundColor','white');
  1292. end
  1293. % --- Executes during object creation, after setting all properties.
  1294. function TextboxResliceZRange_CreateFcn(hObject, eventdata, handles)
  1295. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
  1296. set(hObject,'BackgroundColor','white');
  1297. end